package top.yudoge.dogeeditor.llm.memory

/**
 * Session memory holds all memory of active sessions
 *
 * For each session, you got a memory space which you can imagine it like a map(string -> string).
 * The memory space has an expiration time. Memory will invalidate immediately after these time.
 * All the key-value pair will be revoked!
 *
 * This class is not thread-safe, because there is no concurrent access in one session.
 */
interface SessionMemory {

    /**
     * Create a new session for `sessionId` with given `expireTimeInMS`
     * @param sessionId session id
     * @param expireTimeInMS expire time in milliseconds
     * @return true if success, false if session already exists
     */
    fun newSession(sessionId: String, expireTimeInMS: Long): Boolean

    /**
     * Renew the session(sessionId) with given `expireTimeInMS`
     * @param sessionId session id
     * @param expireTimeInMS expire time in milliseconds
     * @return true if success, false if session not exists
     */
    fun renewSession(sessionId: String, expireTimeInMS: Long): Boolean

    /**
     * Get the value corresponding to `key` in the memory space of session(sessionId)
     * @param sessionId session id
     * @param key key
     * @return value if exists, null if not
     */
    fun get(sessionId: String, key: String): String?

    /**
     * Put a key-value pair into the memory space of session(sessionId)
     * @param sessionId session id
     * @param key key
     * @param value value
     * @return true if success, false if session not exists
     */
    fun put(sessionId: String, key: String, value: String): Boolean

    fun putMultiple(sessionId: String, vararg pairs: Pair<String, String>): Boolean {
        var anyFailure = false
        pairs.forEach {
            if (!put(sessionId, it.first, it.second)) {
                anyFailure = true
            }
        }
        return !anyFailure
    }

    /**
     * Put a key-value pair into the memory space of session(sessionId) if the key is absent
     * @param sessionId session id
     * @param key key
     * @param value value
     * @return true if success, false if session not exists or key already exists
     */
    fun putIfAbsent(sessionId: String, key: String, value: String): Boolean {
        if (contains(sessionId, key)) {
            return false
        }
        return put(sessionId, key, value)
    }

    /**
     * Check if the memory space of session(sessionId) contains the key
     * @param sessionId session id
     * @param key key
     * @return true if contains, false if not
     */
    fun contains(sessionId: String, key: String): Boolean

    /**
     * Check if the session(sessionId) exists
     * @param sessionId session id
     * @return true if exists, false if not
     */
    fun containsSession(sessionId: String): Boolean

    /**
     * Remove the key-value pair from the memory space of session(sessionId)
     * @param sessionId session id
     * @param key key to be removed
     * @return true if success, false if session not exists or key not exists
     */
    fun remove(sessionId: String, key: String): Boolean

    /**
     * Remove the key-value pairs from the memory space of session(sessionId)
     */
    fun removeMultiple(sessionId: String, vararg keys: String): Boolean {
        var anyFailure = false
        keys.forEach {
            if (!remove(sessionId, it)) {
                anyFailure = true
            }
        }
        return !anyFailure
    }

    /**
     * Revoke the memory space of session(sessionId)
     * @param sessionId session id
     * @return true if success, false if session not exists
     */
    fun revoke(sessionId: String): Boolean

}